{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Use Flax NNX and Linen together\n",
    "\n",
    "This guide is for existing Flax users who want to make their codebase a mixture of Flax Linen and Flax NNX `Module`s, which is made possible thanks to the `flax.nnx.bridge` API.\n",
    "\n",
    "This will be helpful if you:\n",
    "\n",
    "* Want to migrate your codebase to NNX gradually, one module at a time;\n",
    "* Have external dependency that already moved to NNX but you haven't, or is still in Linen while you've moved to NNX.\n",
    "\n",
    "We hope this allows you to move and try out NNX at your own pace, and leverage the best of both worlds. We will also talk about how to resolve the caveats of interoperating the two APIs, on a few aspects that they are fundamentally different.\n",
    "\n",
    "**Note**:\n",
    "\n",
    "This guide is about glueing Linen and NNX modules. To migrate an existing Linen module to NNX, check out the [Migrate from Flax Linen to Flax NNX](https://flax.readthedocs.io/en/latest/guides/linen_to_nnx.html) guide.\n",
    "\n",
    "And all built-in Linen layers should have equivalent NNX versions! Check out the list of [Built-in NNX layers](https://flax.readthedocs.io/en/latest/api_reference/flax.nnx/nn/index.html)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "os.environ[\"XLA_FLAGS\"] = '--xla_force_host_platform_device_count=8'\n",
    "\n",
    "from flax import nnx\n",
    "from flax import linen as nn\n",
    "from flax.nnx import bridge\n",
    "import jax\n",
    "from jax import numpy as jnp\n",
    "from jax.experimental import mesh_utils\n",
    "from typing import *"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Submodule is all you need\n",
    "\n",
    "A Flax model is always a tree of modules - either old Linen modules (`flax.linen.Module`, usually written as `nn.Module`) or NNX modules (`nnx.Module`).\n",
    "\n",
    "An `nnx.bridge` wrapper glues the two types together, in both ways:\n",
    "\n",
    "* `nnx.bridge.ToNNX`: Convert a Linen module to NNX, so that it can be a submodule of another NNX module, or stand alone to be trained in NNX-style training loops.\n",
    "* `nnx.bridge.ToLinen`: Vice versa, convert a NNX module to Linen.\n",
    "\n",
    "This means you can move in either top-down or bottom-up behavior: convert the whole Linen module to NNX, then gradually move down, or convert all the lower level modules to NNX then move up."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The Basics\n",
    "\n",
    "There are two fundamental difference between Linen and NNX modules:\n",
    "\n",
    "* **Stateless vs. stateful**: Linen module instances are stateless: variables are returned from a purely functional `.init()` call and managed separately. NNX modules, however, owns its variables as instance attributes.\n",
    "\n",
    "* **Lazy vs. eager**: Linen modules only allocate space to create variables when they actually see their input. Whereas NNX module instances create their variables the moment they are instantiated, without seeing a sample input.\n",
    "\n",
    "With that in mind, let's look at how the `nnx.bridge` wrappers tackle the differences.\n",
    "\n",
    "### Linen -> NNX\n",
    "\n",
    "Since Linen modules may require an input to create variables, we semi-formally supported lazy initialization in the NNX modules converted from Linen. The Linen variables are created when you give it a sample input.\n",
    "\n",
    "For you, it's calling `nnx.bridge.lazy_init()` where you call `module.init()` in Linen code.\n",
    "\n",
    "(Note: you can call `nnx.display` upon any NNX module to inspect all its variables and state.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<script> (()=>{ if (customElements.get('treescope-container') === undefined) { class TreescopeContainer extends HTMLElement { constructor() { super(); this.attachShadow({mode: \"open\"}); this.defns = {}; this.state = {}; } } customElements.define(\"treescope-container\", TreescopeContainer); } if (customElements.get('treescope-run-here') === undefined) { class RunHere extends HTMLElement { constructor() { super() } connectedCallback() { const run = child => { const fn = new Function(child.textContent); child.textContent = \"\"; fn.call(this); this.remove(); }; const child = this.querySelector(\"script\"); if (child) { run(child); } else { new MutationObserver(()=>{ run(this.querySelector(\"script\")); }).observe(this, {childList: true}); } } } customElements.define(\"treescope-run-here\", RunHere); } })(); </script> <treescope-container class=\"treescope_out_7a625519c112482ea3aa899dacf66732\" style=\"display:block\"></treescope-container> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_7a625519c112482ea3aa899dacf66732\")) .filter((elt) => !elt.dataset.setup) )[0]; root.dataset.setup = 1; const msg = document.createElement(\"span\"); msg.style = \"color: #cccccc; font-family: monospace;\"; msg.textContent = \"(Loading...)\"; root.state.loadingMsg = msg; root.shadowRoot.appendChild(msg); root.state.chain = new Promise((resolve, reject) => { const observer = new IntersectionObserver((entries) => { for (const entry of entries) { if (entry.isIntersecting) { resolve(); observer.disconnect(); return; } } }, {rootMargin: \"1000px\"}); window.setTimeout(() => { observer.observe(root); }, 0); }); root.state.deferring = false; const _insertNode = (node) => { for (let oldScript of node.querySelectorAll(\"script\")) { let newScript = document.createElement(\"script\"); newScript.type = oldScript.type; newScript.textContent = oldScript.textContent; oldScript.parentNode.replaceChild(newScript, oldScript); } if (root.state.loadingMsg) { root.state.loadingMsg.remove(); root.state.loadingMsg = null; } root.shadowRoot.appendChild(node); }; root.defns.insertContent = ((contentNode, compressed) => { if (compressed) { root.state.deferring = true; } if (root.state.deferring) { root.state.chain = (async () => { await root.state.chain; if (compressed) { const encoded = contentNode.textContent; const blob = new Blob([ Uint8Array.from(atob(encoded), (m) => m.codePointAt(0)) ]); const reader = blob.stream().pipeThrough( new DecompressionStream(\"deflate\") ).pipeThrough( new TextDecoderStream(\"utf-8\") ).getReader(); const parts = []; while (true) { const step = await reader.read(); if (step.done) { break; } parts.push(step.value); } const tpl = document.createElement('template'); tpl.innerHTML = parts.join(\"\"); _insertNode(tpl.content); } else { _insertNode(contentNode.content); } })(); } else { _insertNode(contentNode.content); } }); </script></treescope-run-here><div style=\"display:none\"> <script type=\"application/octet-stream\" >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</script> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_7a625519c112482ea3aa899dacf66732\")) .filter((elt) => !elt.dataset['step0']) )[0]; root.dataset['step0'] = 1; root.defns.insertContent( this.parentNode.querySelector('script[type=\"application/octet-stream\"]'), true ); this.parentNode.remove(); </script></treescope-run-here> </div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div style=\"display:none\"> <script type=\"application/octet-stream\" >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</script> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_7a625519c112482ea3aa899dacf66732\")) .filter((elt) => !elt.dataset['step1']) )[0]; root.dataset['step1'] = 1; root.defns.insertContent( this.parentNode.querySelector('script[type=\"application/octet-stream\"]'), true ); this.parentNode.remove(); </script></treescope-run-here> </div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "class LinenDot(nn.Module):\n",
    "  out_dim: int\n",
    "  w_init: Callable[..., Any] = nn.initializers.lecun_normal()\n",
    "  @nn.compact\n",
    "  def __call__(self, x):\n",
    "    # Linen might need the input shape to create the weight!\n",
    "    w = self.param('w', self.w_init, (x.shape[-1], self.out_dim))\n",
    "    return x @ w\n",
    "\n",
    "x = jax.random.normal(jax.random.key(42), (4, 32))\n",
    "model = bridge.ToNNX(LinenDot(64),\n",
    "                     rngs=nnx.Rngs(0))  # => `model = LinenDot(64)` in Linen\n",
    "bridge.lazy_init(model, x)              # => `var = model.init(key, x)` in Linen\n",
    "y = model(x)                            # => `y = model.apply(var, x)` in Linen\n",
    "\n",
    "nnx.display(model)\n",
    "\n",
    "# In-place swap your weight array and the model still works!\n",
    "model.w.value = jax.random.normal(jax.random.key(1), (32, 64))\n",
    "assert not jnp.allclose(y, model(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`nnx.bridge.lazy_init` also works even if the top-level module is a pure-NNX one, so you can do sub-moduling as you wish:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<script> (()=>{ if (customElements.get('treescope-container') === undefined) { class TreescopeContainer extends HTMLElement { constructor() { super(); this.attachShadow({mode: \"open\"}); this.defns = {}; this.state = {}; } } customElements.define(\"treescope-container\", TreescopeContainer); } if (customElements.get('treescope-run-here') === undefined) { class RunHere extends HTMLElement { constructor() { super() } connectedCallback() { const run = child => { const fn = new Function(child.textContent); child.textContent = \"\"; fn.call(this); this.remove(); }; const child = this.querySelector(\"script\"); if (child) { run(child); } else { new MutationObserver(()=>{ run(this.querySelector(\"script\")); }).observe(this, {childList: true}); } } } customElements.define(\"treescope-run-here\", RunHere); } })(); </script> <treescope-container class=\"treescope_out_51238e6b592f4415a7fc6fc089ddda0e\" style=\"display:block\"></treescope-container> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_51238e6b592f4415a7fc6fc089ddda0e\")) .filter((elt) => !elt.dataset.setup) )[0]; root.dataset.setup = 1; const msg = document.createElement(\"span\"); msg.style = \"color: #cccccc; font-family: monospace;\"; msg.textContent = \"(Loading...)\"; root.state.loadingMsg = msg; root.shadowRoot.appendChild(msg); root.state.chain = new Promise((resolve, reject) => { const observer = new IntersectionObserver((entries) => { for (const entry of entries) { if (entry.isIntersecting) { resolve(); observer.disconnect(); return; } } }, {rootMargin: \"1000px\"}); window.setTimeout(() => { observer.observe(root); }, 0); }); root.state.deferring = false; const _insertNode = (node) => { for (let oldScript of node.querySelectorAll(\"script\")) { let newScript = document.createElement(\"script\"); newScript.type = oldScript.type; newScript.textContent = oldScript.textContent; oldScript.parentNode.replaceChild(newScript, oldScript); } if (root.state.loadingMsg) { root.state.loadingMsg.remove(); root.state.loadingMsg = null; } root.shadowRoot.appendChild(node); }; root.defns.insertContent = ((contentNode, compressed) => { if (compressed) { root.state.deferring = true; } if (root.state.deferring) { root.state.chain = (async () => { await root.state.chain; if (compressed) { const encoded = contentNode.textContent; const blob = new Blob([ Uint8Array.from(atob(encoded), (m) => m.codePointAt(0)) ]); const reader = blob.stream().pipeThrough( new DecompressionStream(\"deflate\") ).pipeThrough( new TextDecoderStream(\"utf-8\") ).getReader(); const parts = []; while (true) { const step = await reader.read(); if (step.done) { break; } parts.push(step.value); } const tpl = document.createElement('template'); tpl.innerHTML = parts.join(\"\"); _insertNode(tpl.content); } else { _insertNode(contentNode.content); } })(); } else { _insertNode(contentNode.content); } }); </script></treescope-run-here><div style=\"display:none\"> <script type=\"application/octet-stream\" >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</script> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_51238e6b592f4415a7fc6fc089ddda0e\")) .filter((elt) => !elt.dataset['step0']) )[0]; root.dataset['step0'] = 1; root.defns.insertContent( this.parentNode.querySelector('script[type=\"application/octet-stream\"]'), true ); this.parentNode.remove(); </script></treescope-run-here> </div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div style=\"display:none\"> <script type=\"application/octet-stream\" >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</script> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_51238e6b592f4415a7fc6fc089ddda0e\")) .filter((elt) => !elt.dataset['step1']) )[0]; root.dataset['step1'] = 1; root.defns.insertContent( this.parentNode.querySelector('script[type=\"application/octet-stream\"]'), true ); this.parentNode.remove(); </script></treescope-run-here> </div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "class NNXOuter(nnx.Module):\n",
    "  def __init__(self, out_dim: int, rngs: nnx.Rngs):\n",
    "    self.dot = nnx.bridge.ToNNX(LinenDot(out_dim), rngs=rngs)\n",
    "    self.b = nnx.Param(jax.random.uniform(rngs.params(), (1, out_dim,)))\n",
    "\n",
    "  def __call__(self, x):\n",
    "    return self.dot(x) + self.b\n",
    "\n",
    "x = jax.random.normal(jax.random.key(42), (4, 32))\n",
    "model = bridge.lazy_init(NNXOuter(64, rngs=nnx.Rngs(0)), x)  # Can fit into one line\n",
    "nnx.display(model)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The Linen weight is already converted to a typical NNX variable, which is a thin wrapper of the actual JAX array value within. Here, `w` is an `nnx.Param` because it belongs to the `params` collection of `LinenDot` module.\n",
    "\n",
    "We will talk more about different collections and types in the [NNX Variable <-> Linen Collections](#variable-types-vs-collections) section. Right now, just know that they are converted to NNX variables like native ones."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "assert isinstance(model.dot.w, nnx.Param)\n",
    "assert isinstance(model.dot.w.value, jax.Array)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you create this model witout using `nnx.bridge.lazy_init`, the NNX variables defined outside will be initialized as usual, but the Linen part (wrapped inside `ToNNX`) will not."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<script> (()=>{ if (customElements.get('treescope-container') === undefined) { class TreescopeContainer extends HTMLElement { constructor() { super(); this.attachShadow({mode: \"open\"}); this.defns = {}; this.state = {}; } } customElements.define(\"treescope-container\", TreescopeContainer); } if (customElements.get('treescope-run-here') === undefined) { class RunHere extends HTMLElement { constructor() { super() } connectedCallback() { const run = child => { const fn = new Function(child.textContent); child.textContent = \"\"; fn.call(this); this.remove(); }; const child = this.querySelector(\"script\"); if (child) { run(child); } else { new MutationObserver(()=>{ run(this.querySelector(\"script\")); }).observe(this, {childList: true}); } } } customElements.define(\"treescope-run-here\", RunHere); } })(); </script> <treescope-container class=\"treescope_out_acf55118cb8348a8b9ad55ec072c8c1a\" style=\"display:block\"></treescope-container> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_acf55118cb8348a8b9ad55ec072c8c1a\")) .filter((elt) => !elt.dataset.setup) )[0]; root.dataset.setup = 1; const msg = document.createElement(\"span\"); msg.style = \"color: #cccccc; font-family: monospace;\"; msg.textContent = \"(Loading...)\"; root.state.loadingMsg = msg; root.shadowRoot.appendChild(msg); root.state.chain = new Promise((resolve, reject) => { const observer = new IntersectionObserver((entries) => { for (const entry of entries) { if (entry.isIntersecting) { resolve(); observer.disconnect(); return; } } }, {rootMargin: \"1000px\"}); window.setTimeout(() => { observer.observe(root); }, 0); }); root.state.deferring = false; const _insertNode = (node) => { for (let oldScript of node.querySelectorAll(\"script\")) { let newScript = document.createElement(\"script\"); newScript.type = oldScript.type; newScript.textContent = oldScript.textContent; oldScript.parentNode.replaceChild(newScript, oldScript); } if (root.state.loadingMsg) { root.state.loadingMsg.remove(); root.state.loadingMsg = null; } root.shadowRoot.appendChild(node); }; root.defns.insertContent = ((contentNode, compressed) => { if (compressed) { root.state.deferring = true; } if (root.state.deferring) { root.state.chain = (async () => { await root.state.chain; if (compressed) { const encoded = contentNode.textContent; const blob = new Blob([ Uint8Array.from(atob(encoded), (m) => m.codePointAt(0)) ]); const reader = blob.stream().pipeThrough( new DecompressionStream(\"deflate\") ).pipeThrough( new TextDecoderStream(\"utf-8\") ).getReader(); const parts = []; while (true) { const step = await reader.read(); if (step.done) { break; } parts.push(step.value); } const tpl = document.createElement('template'); tpl.innerHTML = parts.join(\"\"); _insertNode(tpl.content); } else { _insertNode(contentNode.content); } })(); } else { _insertNode(contentNode.content); } }); </script></treescope-run-here><div style=\"display:none\"> <script type=\"application/octet-stream\" >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</script> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_acf55118cb8348a8b9ad55ec072c8c1a\")) .filter((elt) => !elt.dataset['step0']) )[0]; root.dataset['step0'] = 1; root.defns.insertContent( this.parentNode.querySelector('script[type=\"application/octet-stream\"]'), true ); this.parentNode.remove(); </script></treescope-run-here> </div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div style=\"display:none\"> <script type=\"application/octet-stream\" >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</script> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_acf55118cb8348a8b9ad55ec072c8c1a\")) .filter((elt) => !elt.dataset['step1']) )[0]; root.dataset['step1'] = 1; root.defns.insertContent( this.parentNode.querySelector('script[type=\"application/octet-stream\"]'), true ); this.parentNode.remove(); </script></treescope-run-here> </div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "partial_model = NNXOuter(64, rngs=nnx.Rngs(0))\n",
    "nnx.display(partial_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<script> (()=>{ if (customElements.get('treescope-container') === undefined) { class TreescopeContainer extends HTMLElement { constructor() { super(); this.attachShadow({mode: \"open\"}); this.defns = {}; this.state = {}; } } customElements.define(\"treescope-container\", TreescopeContainer); } if (customElements.get('treescope-run-here') === undefined) { class RunHere extends HTMLElement { constructor() { super() } connectedCallback() { const run = child => { const fn = new Function(child.textContent); child.textContent = \"\"; fn.call(this); this.remove(); }; const child = this.querySelector(\"script\"); if (child) { run(child); } else { new MutationObserver(()=>{ run(this.querySelector(\"script\")); }).observe(this, {childList: true}); } } } customElements.define(\"treescope-run-here\", RunHere); } })(); </script> <treescope-container class=\"treescope_out_8e27697ae41d4cccae9d79ad4846e0e1\" style=\"display:block\"></treescope-container> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_8e27697ae41d4cccae9d79ad4846e0e1\")) .filter((elt) => !elt.dataset.setup) )[0]; root.dataset.setup = 1; const msg = document.createElement(\"span\"); msg.style = \"color: #cccccc; font-family: monospace;\"; msg.textContent = \"(Loading...)\"; root.state.loadingMsg = msg; root.shadowRoot.appendChild(msg); root.state.chain = new Promise((resolve, reject) => { const observer = new IntersectionObserver((entries) => { for (const entry of entries) { if (entry.isIntersecting) { resolve(); observer.disconnect(); return; } } }, {rootMargin: \"1000px\"}); window.setTimeout(() => { observer.observe(root); }, 0); }); root.state.deferring = false; const _insertNode = (node) => { for (let oldScript of node.querySelectorAll(\"script\")) { let newScript = document.createElement(\"script\"); newScript.type = oldScript.type; newScript.textContent = oldScript.textContent; oldScript.parentNode.replaceChild(newScript, oldScript); } if (root.state.loadingMsg) { root.state.loadingMsg.remove(); root.state.loadingMsg = null; } root.shadowRoot.appendChild(node); }; root.defns.insertContent = ((contentNode, compressed) => { if (compressed) { root.state.deferring = true; } if (root.state.deferring) { root.state.chain = (async () => { await root.state.chain; if (compressed) { const encoded = contentNode.textContent; const blob = new Blob([ Uint8Array.from(atob(encoded), (m) => m.codePointAt(0)) ]); const reader = blob.stream().pipeThrough( new DecompressionStream(\"deflate\") ).pipeThrough( new TextDecoderStream(\"utf-8\") ).getReader(); const parts = []; while (true) { const step = await reader.read(); if (step.done) { break; } parts.push(step.value); } const tpl = document.createElement('template'); tpl.innerHTML = parts.join(\"\"); _insertNode(tpl.content); } else { _insertNode(contentNode.content); } })(); } else { _insertNode(contentNode.content); } }); </script></treescope-run-here><div style=\"display:none\"> <script type=\"application/octet-stream\" >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</script> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_8e27697ae41d4cccae9d79ad4846e0e1\")) .filter((elt) => !elt.dataset['step0']) )[0]; root.dataset['step0'] = 1; root.defns.insertContent( this.parentNode.querySelector('script[type=\"application/octet-stream\"]'), true ); this.parentNode.remove(); </script></treescope-run-here> </div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div style=\"display:none\"> <script type=\"application/octet-stream\" >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</script> <treescope-run-here><script type=\"application/octet-stream\"> const root = ( Array.from(document.getElementsByClassName( \"treescope_out_8e27697ae41d4cccae9d79ad4846e0e1\")) .filter((elt) => !elt.dataset['step1']) )[0]; root.dataset['step1'] = 1; root.defns.insertContent( this.parentNode.querySelector('script[type=\"application/octet-stream\"]'), true ); this.parentNode.remove(); </script></treescope-run-here> </div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "full_model = bridge.lazy_init(partial_model, x)\n",
    "nnx.display(full_model)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NNX -> Linen\n",
    "\n",
    "To convert an NNX module to Linen, you should forward your creation arguments to `bridge.ToLinen` and let it handle the actual creation process.\n",
    "\n",
    "This is because NNX module instance initializes all its variables eagerly when it is created, which consumes memory and compute. On the other hand, Linen modules are stateless, and the typical `init` and `apply` process involves multiple creation of them. So `bridge.to_linen` will handle the actual module creation and make sure no memory is allocated twice."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['params']\n",
      "(32, 64)\n",
      "(4, 64)\n"
     ]
    }
   ],
   "source": [
    "class NNXDot(nnx.Module):\n",
    "  def __init__(self, in_dim: int, out_dim: int, rngs: nnx.Rngs):\n",
    "    self.w = nnx.Param(nnx.initializers.lecun_normal()(\n",
    "      rngs.params(), (in_dim, out_dim)))\n",
    "  def __call__(self, x: jax.Array):\n",
    "    return x @ self.w\n",
    "\n",
    "x = jax.random.normal(jax.random.key(42), (4, 32))\n",
    "# Pass in the arguments, not an actual module\n",
    "model = bridge.to_linen(NNXDot, 32, out_dim=64)\n",
    "variables = model.init(jax.random.key(0), x)\n",
    "y = model.apply(variables, x)\n",
    "\n",
    "print(list(variables.keys()))\n",
    "print(variables['params']['w'].shape)  # => (32, 64)\n",
    "print(y.shape)                         # => (4, 64)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`bridge.to_linen` is actually a convenience wrapper around the Linen module `bridge.ToLinen`. Most likely you won't need to use `ToLinen` directly at all, unless you are using one of the built-in arguments of `ToLinen`. For example, if your NNX module doesn't want to be initialized with RNG handling:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "class NNXAddConstant(nnx.Module):\n",
    "  def __init__(self):\n",
    "    self.constant = nnx.Variable(jnp.array(1))\n",
    "  def __call__(self, x):\n",
    "    return x + self.constant\n",
    "\n",
    "# You have to use `skip_rng=True` because this module's `__init__` don't\n",
    "# take `rng` as argument\n",
    "model = bridge.ToLinen(NNXAddConstant, skip_rng=True)\n",
    "y, var = model.init_with_output(jax.random.key(0), x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similar to `ToNNX`, you can use `ToLinen` to create a submodule of another Linen module."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(32, 64) (1, 64) (4, 64)\n"
     ]
    }
   ],
   "source": [
    "class LinenOuter(nn.Module):\n",
    "  out_dim: int\n",
    "  @nn.compact\n",
    "  def __call__(self, x):\n",
    "    dot = bridge.to_linen(NNXDot, x.shape[-1], self.out_dim)\n",
    "    b = self.param('b', nn.initializers.lecun_normal(), (1, self.out_dim))\n",
    "    return dot(x) + b\n",
    "\n",
    "x = jax.random.normal(jax.random.key(42), (4, 32))\n",
    "model = LinenOuter(out_dim=64)\n",
    "y, variables = model.init_with_output(jax.random.key(0), x)\n",
    "w, b = variables['params']['ToLinen_0']['w'], variables['params']['b']\n",
    "print(w.shape, b.shape, y.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Handling RNG keys\n",
    "\n",
    "All Flax modules, Linen or NNX, automatically handle the RNG keys for variable creation and random layers like dropouts. However, the specific logics of RNG key splitting are different, so you cannot generate the same params between Linen and NNX modules, even if you pass in same keys.\n",
    "\n",
    "Another difference is that NNX modules are stateful, so they can track and update the RNG keys within themselves.\n",
    "\n",
    "### Linen to NNX\n",
    "\n",
    "If you convert a Linen module to NNX, you enjoy the stateful benefit and don't need to pass in extra RNG keys on every module call. You can use always `nnx.reseed` to reset the RNG state within."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = jax.random.normal(jax.random.key(42), (4, 32))\n",
    "model = bridge.ToNNX(nn.Dropout(rate=0.5, deterministic=False), rngs=nnx.Rngs(dropout=0))\n",
    "# We don't really need to call lazy_init because no extra params were created here,\n",
    "# but it's a good practice to always add this line.\n",
    "bridge.lazy_init(model, x)\n",
    "y1, y2 = model(x), model(x)\n",
    "assert not jnp.allclose(y1, y2)  # Two runs yield different outputs!\n",
    "\n",
    "# Reset the dropout RNG seed, so that next model run will be the same as the first.\n",
    "nnx.reseed(model, dropout=0)\n",
    "y1 = model(x)\n",
    "nnx.reseed(model, dropout=0)\n",
    "y2 = model(x)\n",
    "assert jnp.allclose(y1, y2)  # Two runs yield the same output!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NNX to Linen\n",
    "\n",
    "`to_linen` will automatically take the `rngs` dict argument and create a `Rngs` object that is passed to the underlying NNX module via the `rngs` keyword argument. If the module holds internal `RngState`, `to_linen` will always call reseed using the `rngs` dict to reset the RNG state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "x = jax.random.normal(jax.random.key(42), (4, 32))\n",
    "model = bridge.to_linen(nnx.Dropout, rate=0.5)\n",
    "variables = model.init({'dropout': jax.random.key(0)}, x)\n",
    "\n",
    "# Just pass different RNG keys for every `apply()` call.\n",
    "y1 = model.apply(variables, x, rngs={'dropout': jax.random.key(1)})\n",
    "y2 = model.apply(variables, x, rngs={'dropout': jax.random.key(2)})\n",
    "assert not jnp.allclose(y1, y2)  # Every call yields different output!\n",
    "y3 = model.apply(variables, x, rngs={'dropout': jax.random.key(1)})\n",
    "assert jnp.allclose(y1, y3)      # When you use same top-level RNG, outputs are same"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## NNX variable types vs. Linen collections\n",
    "\n",
    "When you want to group some variables as one category, in Linen you use different collections; in NNX, since all variables shall be top-level Python attributes, you use different variable types.\n",
    "\n",
    "Therefore, when mixing Linen and NNX modules, Flax must know the 1-to-1 mapping between Linen collections and NNX variable types, so that `ToNNX` and `ToLinen` can do the conversion automatically.\n",
    "\n",
    "Flax keeps a registry for this, and it already covers all Flax's built-in Linen collections. You can register extra mapping of NNX variable type and Linen collection names using `nnx.register_variable_name_type_pair`.\n",
    "\n",
    "### Linen to NNX\n",
    "\n",
    "For any collection of your Linen module, `ToNNX` will convert all its endpoint arrays (aka. leaves) to a subtype of `nnx.Variable`, either from registry or automatically created on-the-fly.\n",
    "\n",
    "(However, we still keep the whole collection as one class attribute, because Linen modules may have duplicated names over different collections.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[38;2;79;201;177mParam\u001b[0m\u001b[38;2;255;213;3m(\u001b[0m\u001b[38;2;105;105;105m # 12 (48 B)\u001b[0m\n",
      "  \u001b[38;2;156;220;254mvalue\u001b[0m\u001b[38;2;212;212;212m=\u001b[0mArray([[ 0.53824717,  0.7668343 , -0.38585317],\n",
      "         [-0.35335615, -0.5244857 , -0.43152452],\n",
      "         [-1.0662307 ,  0.14089198, -0.16519307],\n",
      "         [ 0.3971692 ,  0.43213558, -0.461545  ]], dtype=float32)\n",
      "\u001b[38;2;255;213;3m)\u001b[0m\n",
      "\u001b[38;2;79;201;177mParam\u001b[0m\u001b[38;2;255;213;3m(\u001b[0m\u001b[38;2;105;105;105m # 3 (12 B)\u001b[0m\n",
      "  \u001b[38;2;156;220;254mvalue\u001b[0m\u001b[38;2;212;212;212m=\u001b[0mArray([0., 0., 0.], dtype=float32)\n",
      "\u001b[38;2;255;213;3m)\u001b[0m\n",
      "\u001b[38;2;79;201;177mcounter\u001b[0m\u001b[38;2;255;213;3m(\u001b[0m\u001b[38;2;105;105;105m # 1 (4 B)\u001b[0m\n",
      "  \u001b[38;2;156;220;254mvalue\u001b[0m\u001b[38;2;212;212;212m=\u001b[0mArray(0, dtype=int32)\n",
      "\u001b[38;2;255;213;3m)\u001b[0m\n",
      "<class 'flax.nnx.variablelib.counter'>\n",
      "(Intermediate( # 1 (4 B)\n",
      "  value=Array(0.5475821, dtype=float32)\n",
      "),)\n"
     ]
    }
   ],
   "source": [
    "class LinenMultiCollections(nn.Module):\n",
    "  out_dim: int\n",
    "  def setup(self):\n",
    "    self.w = self.param('w', nn.initializers.lecun_normal(), (x.shape[-1], self.out_dim))\n",
    "    self.b = self.param('b', nn.zeros_init(), (self.out_dim,))\n",
    "    self.count = self.variable('counter', 'count', lambda: jnp.zeros((), jnp.int32))\n",
    "\n",
    "  def __call__(self, x):\n",
    "    if not self.is_initializing():\n",
    "      self.count.value += 1\n",
    "    y = x @ self.w + self.b\n",
    "    self.sow('intermediates', 'dot_sum', jnp.sum(y))\n",
    "    return y\n",
    "\n",
    "x = jax.random.normal(jax.random.key(42), (2, 4))\n",
    "model = bridge.lazy_init(bridge.ToNNX(LinenMultiCollections(3), rngs=nnx.Rngs(0)), x)\n",
    "print(model.w)        # Of type `nnx.Param` - note this is still under attribute `params`\n",
    "print(model.b)        # Of type `nnx.Param`\n",
    "print(model.count)    # Of type `counter` - auto-created type from the collection name\n",
    "print(type(model.count))\n",
    "\n",
    "y = model(x, mutable=True)  # Linen's `sow()` needs `mutable=True` to trigger\n",
    "print(model.dot_sum)        # Of type `nnx.Intermediates`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can quickly separate different types of NNX variables apart using `nnx.split`.\n",
    "\n",
    "This can be handy when you only want to set some variables as trainable."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "All Params: ['b', 'w']\n",
      "All Counters: ['count']\n",
      "All the rest (intermediates and RNG keys): ['dot_sum', 'rngs']\n"
     ]
    }
   ],
   "source": [
    "# Separate variables of different types with nnx.split\n",
    "CountType = type(model.count)\n",
    "static, params, counter, the_rest = nnx.split(model, nnx.Param, CountType, ...)\n",
    "print('All Params:', list(params.keys()))\n",
    "print('All Counters:', list(counter.keys()))\n",
    "print('All the rest (intermediates and RNG keys):', list(the_rest.keys()))\n",
    "\n",
    "model = nnx.merge(static, params, counter, the_rest)  # You can merge them back at any time\n",
    "y = model(x, mutable=True)  # still works!"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc9d78ed",
   "metadata": {},
   "source": [
    "    All Params: ['b', 'w']\n",
    "    All Counters: ['count']\n",
    "    All the rest (intermediates and RNG keys): ['dot_sum', 'rngs']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NNX to Linen\n",
    "\n",
    "If you define custom NNX variable types, you should register their names with `nnx.register_variable_name` so that they go to the desired collections."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "All Linen collections: ['nnx', 'LoRAParam', 'params', 'counts']\n",
      "{'w': Array([[ 0.2916921 ,  0.22780475,  0.06553137],\n",
      "       [ 0.17487915, -0.34043145,  0.24764155],\n",
      "       [ 0.6420431 ,  0.6220095 , -0.44769976],\n",
      "       [ 0.11161668,  0.83873135, -0.7446058 ]], dtype=float32)}\n"
     ]
    }
   ],
   "source": [
    "@nnx.register_variable_name('counts', overwrite=True)\n",
    "class Count(nnx.Variable): pass\n",
    "\n",
    "\n",
    "class NNXMultiCollections(nnx.Module):\n",
    "  def __init__(self, din, dout, rngs):\n",
    "    self.w = nnx.Param(nnx.initializers.lecun_normal()(rngs.params(), (din, dout)))\n",
    "    self.lora = nnx.LoRA(din, 3, dout, rngs=rngs)\n",
    "    self.count = Count(jnp.array(0))\n",
    "\n",
    "  def __call__(self, x):\n",
    "    self.count.value += 1\n",
    "    return (x @ self.w.value) + self.lora(x)\n",
    "\n",
    "xkey, pkey, dkey = jax.random.split(jax.random.key(0), 3)\n",
    "x = jax.random.normal(xkey, (2, 4))\n",
    "model = bridge.to_linen(NNXMultiCollections, 4, 3)\n",
    "var = model.init({'params': pkey, 'dropout': dkey}, x)\n",
    "print('All Linen collections:', list(var.keys()))\n",
    "print(var['params'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    All Linen collections: ['LoRAParam', 'params', 'counts']\n",
    "    {'w': Array([[ 0.2916921 ,  0.22780475,  0.06553137],\n",
    "           [ 0.17487915, -0.34043145,  0.24764155],\n",
    "           [ 0.6420431 ,  0.6220095 , -0.44769976],\n",
    "           [ 0.11161668,  0.83873135, -0.7446058 ]], dtype=float32)}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Partition metadata\n",
    "\n",
    "Flax uses a metadata wrapper box over the raw JAX array to annotate how a variable should be sharded.\n",
    "\n",
    "In Linen, this is an optional feature that triggered by using `nn.with_partitioning` on initializers (see more on [Linen partition metadata guide](https://flax.readthedocs.io/en/latest/guides/parallel_training/flax_on_pjit.html)). In NNX, since all NNX variables are wrapped by `nnx.Variable` class anyway, that class will hold the sharding annotations too.\n",
    "\n",
    "The `bridge.ToNNX` and `bridge.ToLinen` API will automatically convert the sharding annotations, if you use the built-in annotation methods (aka. `nn.with_partitioning` for Linen and `nnx.with_partitioning` for NNX).\n",
    "\n",
    "### Linen to NNX\n",
    "\n",
    "Even if you are not using any partition metadata in your Linen module, the variable JAX arrays will be converted to `nnx.Variable`s that wraps the true JAX array within.\n",
    "\n",
    "If you use `nn.with_partitioning` to annotate your Linen module's variables, the annotation will be converted to a `.sharding` field in the corresponding `nnx.Variable`.\n",
    "\n",
    "You can then use `nnx.with_sharding_constraint` to explicitly put the arrays into the annotated partitions within a `jax.jit`-compiled function, to initialize the whole model with every array at the right sharding."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "We have 8 fake JAX devices now to partition this model...\n",
      "<class 'flax.nnx.variables.Param'>\n",
      "('in', 'out')\n",
      "GSPMDSharding({devices=[2,4]<=[8]})\n"
     ]
    }
   ],
   "source": [
    "class LinenDotWithPartitioning(nn.Module):\n",
    "  out_dim: int\n",
    "  @nn.compact\n",
    "  def __call__(self, x):\n",
    "    w = self.param('w', nn.with_partitioning(nn.initializers.lecun_normal(),\n",
    "                                             ('in', 'out')),\n",
    "                   (x.shape[-1], self.out_dim))\n",
    "    return x @ w\n",
    "\n",
    "@nnx.jit\n",
    "def create_sharded_nnx_module(x):\n",
    "  model = bridge.lazy_init(\n",
    "    bridge.ToNNX(LinenDotWithPartitioning(64), rngs=nnx.Rngs(0)), x)\n",
    "  state = nnx.state(model)\n",
    "  sharded_state = nnx.with_sharding_constraint(state, nnx.get_partition_spec(state))\n",
    "  nnx.update(model, sharded_state)\n",
    "  return model\n",
    "\n",
    "\n",
    "print(f'We have {len(jax.devices())} fake JAX devices now to partition this model...')\n",
    "mesh = jax.sharding.Mesh(devices=mesh_utils.create_device_mesh((2, 4)),\n",
    "                         axis_names=('in', 'out'))\n",
    "x = jax.random.normal(jax.random.key(42), (4, 32))\n",
    "with mesh:\n",
    "  model = create_sharded_nnx_module(x)\n",
    "\n",
    "print(type(model.w))           # `nnx.Param`\n",
    "print(model.w.sharding)        # The partition annotation attached with `w`\n",
    "print(model.w.value.sharding)  # The underlying JAX array is sharded across the 2x4 mesh"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "08555a06",
   "metadata": {},
   "source": [
    "    We have 8 fake JAX devices now to partition this model...\n",
    "    <class 'flax.nnx.variables.Param'>\n",
    "    ('in', 'out')\n",
    "    GSPMDSharding({devices=[2,4]<=[8]})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### NNX to Linen\n",
    "\n",
    "If you are not using any metadata feature of the `nnx.Variable` (i.e., no sharding annotation, no registered hooks), the converted Linen module will not add a metadata wrapper to your NNX variable, and you don't need to worry about it.\n",
    "\n",
    "But if you did add sharding annotations to your NNX variables, `ToLinen` will convert them to a default Linen partition metadata class called `bridge.NNXMeta`, retaining all the metadata you put into the NNX variable.\n",
    "\n",
    "Like with any Linen metadata wrappers, you can use `linen.unbox()` to get the raw JAX array tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "GSPMDSharding({devices=[2,4]<=[8]})\n"
     ]
    }
   ],
   "source": [
    "class NNXDotWithParititioning(nnx.Module):\n",
    "  def __init__(self, in_dim: int, out_dim: int, rngs: nnx.Rngs):\n",
    "    init_fn = nnx.with_partitioning(nnx.initializers.lecun_normal(), ('in', 'out'))\n",
    "    self.w = nnx.Param(init_fn(rngs.params(), (in_dim, out_dim)))\n",
    "  def __call__(self, x: jax.Array):\n",
    "    return x @ self.w\n",
    "\n",
    "x = jax.random.normal(jax.random.key(42), (4, 32))\n",
    "\n",
    "@jax.jit\n",
    "def create_sharded_variables(key, x):\n",
    "  model = bridge.to_linen(NNXDotWithParititioning, 32, 64)\n",
    "  variables = model.init(key, x)\n",
    "  # A `NNXMeta` wrapper of the underlying `nnx.Param`\n",
    "  assert type(variables['params']['w']) == bridge.NNXMeta\n",
    "  # The annotation coming from the `nnx.Param` => (in, out)\n",
    "  assert variables['params']['w'].metadata['sharding'] == ('in', 'out')\n",
    "\n",
    "  unboxed_variables = nn.unbox(variables)\n",
    "  variable_pspecs = nn.get_partition_spec(variables)\n",
    "  assert isinstance(unboxed_variables['params']['w'], jax.Array)\n",
    "  assert variable_pspecs['params']['w'] == jax.sharding.PartitionSpec('in', 'out')\n",
    "\n",
    "  sharded_vars = jax.tree.map(jax.lax.with_sharding_constraint,\n",
    "                              nn.unbox(variables),\n",
    "                              nn.get_partition_spec(variables))\n",
    "  return sharded_vars\n",
    "\n",
    "with mesh:\n",
    "  variables = create_sharded_variables(jax.random.key(0), x)\n",
    "\n",
    "# The underlying JAX array is sharded across the 2x4 mesh\n",
    "print(variables['params']['w'].sharding)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    GSPMDSharding({devices=[2,4]<=[8]})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Lifted transforms\n",
    "\n",
    "In general, if you want to apply Linen/NNX-style lifted transforms upon an `nnx.bridge`-converted module, just go ahead and do it in the usual Linen/NNX syntax.\n",
    "\n",
    "For Linen-style transforms, note that `bridge.ToLinen` is the top level module class, so you may want to just use it as the first argument of your transforms (which needs to be a `linen.Module` class in most cases)\n",
    "\n",
    "### Linen to NNX\n",
    "\n",
    "NNX style lifted transforms are similar to JAX transforms, and they work on functions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(4, 32, 64)\n",
      "(4, 64)\n"
     ]
    }
   ],
   "source": [
    "class NNXVmapped(nnx.Module):\n",
    "  def __init__(self, out_dim: int, vmap_axis_size: int, rngs: nnx.Rngs):\n",
    "    self.linen_dot = nnx.bridge.ToNNX(nn.Dense(out_dim, use_bias=False), rngs=rngs)\n",
    "    self.vmap_axis_size = vmap_axis_size\n",
    "\n",
    "  def __call__(self, x):\n",
    "\n",
    "    @nnx.split_rngs(splits=self.vmap_axis_size)\n",
    "    @nnx.vmap(in_axes=(0, 0), axis_size=self.vmap_axis_size)\n",
    "    def vmap_fn(submodule, x):\n",
    "      return submodule(x)\n",
    "\n",
    "    return vmap_fn(self.linen_dot, x)\n",
    "\n",
    "x = jax.random.normal(jax.random.key(0), (4, 32))\n",
    "model = bridge.lazy_init(NNXVmapped(64, 4, rngs=nnx.Rngs(0)), x)\n",
    "\n",
    "print(model.linen_dot.kernel.shape) # (4, 32, 64) - first axis with dim 4 got vmapped\n",
    "y = model(x)\n",
    "print(y.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "    (4, 32, 64)\n",
    "    (4, 64)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "61a1ac21",
   "metadata": {},
   "source": [
    "### NNX to Linen\n",
    "\n",
    "Note that `bridge.ToLinen` is the top level module class, so you may want to just use it as the first argument of your transforms (which needs to be a `linen.Module` class in most cases).\n",
    "\n",
    "`ToLien` can naturally be used with Linen transforms like `nn.vmap` or `nn.scan`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(4, 32, 64)\n",
      "(4, 64)\n"
     ]
    }
   ],
   "source": [
    "class LinenVmapped(nn.Module):\n",
    "  dout: int\n",
    "  @nn.compact\n",
    "  def __call__(self, x):\n",
    "    inner = nn.vmap(bridge.ToLinen, variable_axes={'params': 0}, split_rngs={'params': True}\n",
    "                    )(nnx.Linear, args=(x.shape[-1], self.dout))\n",
    "    return inner(x)\n",
    "\n",
    "x = jax.random.normal(jax.random.key(42), (4, 32))\n",
    "model = LinenVmapped(64)\n",
    "var = model.init(jax.random.key(0), x)\n",
    "print(var['params']['VmapToLinen_0']['kernel'].shape)  # (4, 32, 64) - leading dim 4 got vmapped\n",
    "y = model.apply(var, x)\n",
    "print(y.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "178d2b2f",
   "metadata": {},
   "source": [
    "    (4, 32, 64)\n",
    "    (4, 64)"
   ]
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "formats": "ipynb,md:myst",
   "main_language": "python"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
